package com.zyjc.city.httpclient;


import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.SecureRandom;

/***
 * 接口调用示例
 * @author yangwei
 * @date 2018-03-07 09:26:38
 */
public class CqcInterfaceDemo {
    private final static String BASE_URL = "http://xxxx.xxxx.xxxx:9000";
    private final static String CHARSET = "UTF-8";
    private final static int BUFFER_SIZE = 4096;

    /***
     * 入口
     * @param args
     */
    public static void main(String[] args){
        //渠道编码
        String channelCode = "***";
        //密钥
        String desKey = "****";
        CqcInterfaceDemo cqcInterfaceDemo = new CqcInterfaceDemo();
        cqcInterfaceDemo.getToken(channelCode,desKey);


    }

    /***
     * 获取token
     * @param channelCode
     * @param desKey
     */
    public void getToken(String channelCode,String desKey){
        try{
            String url = BASE_URL+"/openplat-sys-core/api/interface/sys/channelinterface/createtoken?channelCode="+channelCode;
            String msg = "{}";
            String result = callInterface(url,msg,desKey);
            System.out.println("result:"+result);
        }
        catch(Exception ex){
            ex.printStackTrace();
        }
    }

    /***
     * 调用接口，并处理加解密
     * @param url
     * @param msg
     * @param desKey
     * @throws Exception
     */
    private String callInterface(String url,String msg,String desKey)throws Exception{
        if(msg == null){
            msg = "";
        }
        //参数加密
        byte[] paraBytes = encryptDES(msg.getBytes(CHARSET), desKey);
        //调用HTTP接口
        byte[] resultEncodeBytes = callStreamByte("POST",url,paraBytes);
        //返回结果解密
        byte[] resultBytes = decryptDES(resultEncodeBytes,desKey);
        //返回结果构造成字符串
        String result = new String(resultBytes,CHARSET);
        return result;
    }

    /***
     * 流方式提交
     * @requestMehtod 设置请求类型，可以为POST、PUT
     * @param pathUrl
     * @param msg
     * @return
     * @throws Exception
     */
    public byte[] callStreamByte(String requestMehtod,String pathUrl,byte[] requestStringBytes)throws Exception{
        HttpURLConnection httpConn = null;
        try{
            URL url = new URL(pathUrl);
            httpConn = (HttpURLConnection) url.openConnection();

            // //设置连接属性
            httpConn.setDoOutput(true);// 使用 URL 连接进行输出
            httpConn.setDoInput(true);// 使用 URL 连接进行输入
            httpConn.setUseCaches(false);// 忽略缓存
            httpConn.setRequestMethod("POST");// 设置URL请求方法


            //报文长度
            int len = 0;
            if(requestStringBytes != null){
                len = requestStringBytes.length;
            }
            httpConn.setRequestProperty("Content-length", "" + len);
            httpConn.setRequestProperty("Charset", CHARSET);
            httpConn.setRequestProperty("Content-Type", "application/octet-stream");


            // 建立输出流，并写入数据
            OutputStream outputStream = httpConn.getOutputStream();
            if(requestStringBytes != null){
                outputStream.write(requestStringBytes);
            }
            outputStream.close();
            // 获得响应状态
            int responseCode = httpConn.getResponseCode();
            //StringBuffer sb = new StringBuffer();
            byte[] result = null;
            if (HttpURLConnection.HTTP_OK == responseCode || HttpURLConnection.HTTP_NO_CONTENT == responseCode) {// 连接成功

                InputStream in = httpConn.getInputStream();

                result = converStreamToBytes(in);
                in.close();
            }
            else{
                System.out.println("返回HTTP状态:"+responseCode);
                if(responseCode>=400){
                    throw new Exception("HTTP返回错误状态:["+responseCode+"]");
                }
            }
            return result;
        }
        catch(Exception e){
            System.out.println("访问["+pathUrl+"]"+e);
            throw e;
        }
        finally{
            if(httpConn != null){
                httpConn.disconnect();
            }
        }
    }

    /***
     * 获取返回的字节数组
     *
     * @param is
     * @return
     * @throws Exception
     */
    public byte[] converStreamToBytes( InputStream in) throws Exception {
        byte[] result = null;
        try {
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] data = new byte[BUFFER_SIZE];
            int count = -1;
            while((count = in.read(data,0,BUFFER_SIZE)) != -1)
                outStream.write(data, 0, count);

            data = null;
            result = outStream.toByteArray();
            outStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /***
     * DES加密,DES对称属于对称加密
     * @param str 待加密码字符串
     * @param desKey DES密钥,长度必须8的倍数
     * @return
     * @throws Exception
     */
    public static byte[] encryptDES(byte[] bytes,String desKey)throws Exception{
        try{
            if(bytes == null){
                return null;
            }
            SecureRandom sr = new SecureRandom();
            DESKeySpec dks = new DESKeySpec(desKey.getBytes());
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey secretKey = keyFactory.generateSecret(dks);
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey,sr);
            byte[] result = cipher.doFinal(bytes);
            return result;
        }
        catch(Exception ex){
            System.out.println("DES加密失败,"+ex);
            throw ex;
        }
    }

    /***
     * DES解密
     * @param bytes
     * @param desKey
     * @return
     * @throws Exception
     */
    public static byte[] decryptDES(byte[] bytes,String desKey)throws Exception{
        try{
            if(bytes == null){
                return null;
            }
            SecureRandom sr = new SecureRandom();
            DESKeySpec dks = new DESKeySpec(desKey.getBytes());
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey secretKey = keyFactory.generateSecret(dks);
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(Cipher.DECRYPT_MODE, secretKey,sr);
            return cipher.doFinal(bytes);
        }
        catch(Exception ex){
            System.out.println("DES解密失败,"+ex);
            throw ex;
        }
    }

}
